<template>
  <a-modal
    class="image-out-painting"
    v-model:open="visible"
    title="AI 扩图"
    :width="modalWidth"
    :footer="false"
    @cancel="closeModal"
  >
    <a-row gutter="30">
      <a-col :span="spanNum">
        <h4 v-if="resultImageUrl">原图</h4>
        <img :src="picture?.url" :alt="picture?.name" style="max-width: 100%" />
      </a-col>
      <a-col :span="24 - spanNum">
        <h4 v-if="resultImageUrl">效果图</h4>
        <img
          v-if="resultImageUrl"
          :src="resultImageUrl"
          :alt="picture?.name"
          style="max-width: 100%"
        />
      </a-col>
    </a-row>
    <div style="margin-bottom: 16px" />
    <a-flex justify="center" gap="16">
      <a-button
        v-if="!resultImageUrl"
        type="primary"
        ghost
        :loading="expandLoading"
        @click="createPictureOutTask"
      >
        {{ expandLoading ? '正在扩图...' : '开始扩图' }}
      </a-button>
      <a-button
        v-if="resultImageUrl"
        type="primary"
        ghost
        :loading="expandLoading"
        @click="createPictureOutTask"
      >
        {{ expandLoading ? '正在扩图...' : '不满意，重新扩图' }}
      </a-button>
      <a-button v-if="resultImageUrl" type="primary" :loading="uploading" @click="handleUpload">
        应用效果图
      </a-button>
    </a-flex>
  </a-modal>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import {
  createPictureOutPaintingTaskUsingPost,
  getPictureOutPaintingTaskUsingGet,
  uploadPictureByUrlUsingPost,
} from '@/api/pictureController.ts'
import { message } from 'ant-design-vue'
import { useLoginUserStore } from '@/stores/useLoginUserStores.ts'

const loginUserStore = useLoginUserStore()
const loginUser = loginUserStore.loginUser

interface Props {
  imageUrl?: string
  picture?: API.PictureVO
  spaceId?: number
  // 图片上传成功后 通过这个函数传递新的图片返回展示
  onSuccess?: (newPicture: API.PictureVO) => void
}

const props = defineProps<Props>()

// 前端保存扩图任务Id
const taskId = ref<string>()
// 扩图效果图
const resultImageUrl = ref<string>()

const expandLoading = ref(false)

/**
 * 创建 AI 扩图任务
 */
const createPictureOutTask = async () => {
  expandLoading.value = true
  if (!loginUser) {
    message.error('请先登录')
    expandLoading.value = false
    return
  }
  if (props.picture?.spaceId !== null) {
    if (loginUser?.id !== props.picture?.userId) {
      message.error('无权操作图片')
      expandLoading.value = false
      return
    }
  } else {
    if (loginUser?.id !== props.picture?.userId && loginUser.userRole !== 'admin') {
      message.error('无权操作图片')
      expandLoading.value = false
      return
    }
  }
  if (!props.picture?.id) {
    message.error('要扩图的图片不存在')
    expandLoading.value = false
    return
  }
  const picWidth = props.picture?.picWidth
  const picHeight = props.picture?.picHeight
  if (
    // @ts-ignore
    picWidth < 512 ||
    // @ts-ignore
    picWidth > 4096 ||
    // @ts-ignore
    picHeight < 512 ||
    // @ts-ignore
    picHeight > 4096
  ) {
    message.error('该图片分辨率不支持 AI 扩图，支持范围：[512像素，4096像素]')
    expandLoading.value = false
    return
  }
  const picFormat = props.picture?.picFormat
  if (
    picFormat !== 'JPG' &&
    picFormat !== 'JPEG' &&
    picFormat !== 'PNG' &&
    picFormat !== 'WEBP' &&
    picFormat !== 'webp'
  ) {
    message.error('该图片格式不支持 AI 扩图，支持格式：[JPG、JPEG、PNG、HEIF、WEBP]')
    expandLoading.value = false
    return
  }
  const res = await createPictureOutPaintingTaskUsingPost({
    pictureId: props.picture?.id,
    // 根据需要设置扩图参数
    parameters: {
      xScale: 2,
      yScale: 2,
    },
  })
  // @ts-ignore
  if (res.data.code === 0 && res.data.data) {
    message.warn('努力扩图中。。。大约需要 25 - 35 秒，请耐心等待，不要退出当前界面', 17)
    // @ts-ignore
    // 保存扩图任务Id
    taskId.value = res.data.data.output?.taskId
    // 开启轮询
    startPolling()
  } else {
    // @ts-ignore
    message.error('扩图任务创建失败，' + res.data.message)
  }
}

/**
 *  定义轮询定时器
 */
// @ts-ignore
let pollingTimer: NodeJS.Timeout = null
/**
 * 开启轮询
 */
const startPolling = () => {
  if (!taskId.value) {
    message.warn('暂无扩图任务')
    return
  }
  pollingTimer = setInterval(async () => {
    try {
      const res = await getPictureOutPaintingTaskUsingGet({
        taskId: taskId.value,
      })
      // @ts-ignore
      if (res.data.code === 0 && res.data.data) {
        const taskResult = res.data.data.output
        if (taskResult?.taskStatus === 'SUCCEEDED') {
          message.success('扩图成功')
          // @ts-ignore
          resultImageUrl.value = taskResult.outputImageUrl
          expandLoading.value = false
          changeModalWidth()
          changeSpan()
          // 任务执行成功，立刻清理轮询
          clearPolling()
        } else if (taskResult?.taskStatus === 'FAILED') {
          message.error('扩图失败，' + res.data.message)
          expandLoading.value = false
          // 任务执行失败，立刻清理轮询
          clearPolling()
        }
      }
    } catch (error) {
      console.log('扩图任务轮询失败，', error)
      // @ts-ignore
      message.error('扩图任务轮询失败，' + error.message)
      expandLoading.value = false
      // 轮询请求失败，立刻清理轮询
      clearPolling()
    }
  }, 2000) // 每三秒请求后端，查询扩图结果
}

/**
 * 清理轮询
 */
const clearPolling = () => {
  if (pollingTimer) {
    clearInterval(pollingTimer)
    pollingTimer = null
    // @ts-ignore
    taskId.value = null
  }
}

const uploading = ref(false)

/**
 * 图片地址上传
 */
const handleUpload = async () => {
  uploading.value = true
  try {
    const params: API.PictureUploadRequest = {
      fileUrl: resultImageUrl.value,
      spaceId: props.spaceId,
    }
    // 如果是更新图片
    if (props.picture) {
      params.id = props.picture.id
    }
    const res = await uploadPictureByUrlUsingPost(params)
    // @ts-ignore
    if (res.data.code === 0 && res.data.data) {
      message.success('应用效果图成功')
      // @ts-ignore
      props.onSuccess?.(res.data.data)
      // @ts-ignore
      // 关闭弹窗
      closeModal()
      resultImageUrl.value = ''
    } else {
      // @ts-ignore
      message.error('应用效果图失败，' + res.data.message)
    }
  } catch (error) {
    // @ts-ignore
    message.error('应用效果图失败，' + error.message)
  }
  uploading.value = false
}

// 分享弹窗是否可见
const visible = ref<boolean>(false)

/**
 * 打开弹窗
 */
const openModal = () => {
  visible.value = true
}
/**
 * 关闭弹窗
 * @param e
 */
const closeModal = (e: MouseEvent) => {
  visible.value = false
}

/**
 * 暴露函数给父组件
 */
defineExpose({
  openModal,
})

// 原图、效果图展示比例
const spanNum = ref<number>()
/**
 * 改变原图、效果图展示比例
 */
const changeSpan = () => {
  if (!resultImageUrl.value) {
    spanNum.value = 24
  } else {
    spanNum.value = 8
  }
}
const modalWidth = ref<number>()
/**
 * 改变弹窗宽度
 */
const changeModalWidth = () => {
  if (resultImageUrl.value) {
    modalWidth.value = 1500
  } else {
    modalWidth.value = 600
  }
}
</script>

<style>
.image-out-painting {
  text-align: center;
}
</style>
